package com.dkts.oil.test;

import com.dkts.oil.mysql.entity.AisPoint;
import com.dkts.oil.postgis.AisPointBatchInsert;
import com.dkts.oil.postgis.ShipInfoBatchInsert;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

public class GeoJsonExporterV2去重和时间排序 {

    // 分段时长阈值：40 分钟（秒）
    private static final long SEGMENT_TIME_GAP = 40 * 60;
    // 编队空间阈值：0.27° ≈ 30 公里
    private static final double FLEET_DISTANCE_THRESHOLD = 0.27;

    public static void main(String[] args) throws Exception {
        String inputCsvPath = args.length > 0 ? args[0] : "C:\\Users\\heyou\\Desktop\\AIS数据.csv";
        String outputDir = args.length > 1 ? args[1] : "output_geojson_v1";
        // 1. 读取 + 去重 + 时间排序 → Map<MMSI, List<AisPoint>>
        Map<String, List<AisPoint>> aisPointsByMmsi = getAisPointsByMmsi(inputCsvPath,  outputDir, "11111");
        System.out.println("全部导出完成！");
    }

    /**
     * 读取 CSV，按 mmsi 分组，按 time 去重并转成 AisPoint
     */
    public static Map<String, List<AisPoint>> getAisPointsByMmsi(String csvFilePath,String outPath,String uuid) {

        Map<String, List<AisPoint>> aisPointsByMmsi = new HashMap<>();
        try (Reader reader = new FileReader(csvFilePath, StandardCharsets.UTF_8)) {
            CSVParser parser = CSVFormat.DEFAULT
                    .withFirstRecordAsHeader()
                    .parse(reader);

            // 1. 按 MMSI 分组
            Map<String, List<CSVRecord>> mmsiMap = new HashMap<>();
            for (CSVRecord record : parser) {
                String mmsi = record.get("mmsi");
                mmsiMap.computeIfAbsent(mmsi, k -> new ArrayList<>()).add(record);
            }

            // 2. 每组内排序 + 去重 + 转对象
            for (Map.Entry<String, List<CSVRecord>> entry : mmsiMap.entrySet()) {
                String mmsi = entry.getKey();
                List<CSVRecord> records = entry.getValue();

                // 按 time 排序（假设 time 为 Unix 秒）
                records.sort(Comparator.comparingLong(r -> Long.parseLong(r.get("time"))));

                // 去重：保留首次出现的 time
                List<CSVRecord> deduped = records.stream()
                        .filter(distinctByKey(r -> r.get("time")))
                        .collect(Collectors.toList());

                // 转成 AisPoint
                List<AisPoint> points = deduped.stream()
                        .map(GeoJsonExporterV2去重和时间排序::toAisPoint)
                        .collect(Collectors.toList());

//                System.out.printf("MMSI=%s 去重前=%d, 去重后=%d%n",
//                        mmsi, records.size(), deduped.size());

                aisPointsByMmsi.put(mmsi, points);
            }
        } catch (Exception e) {
            System.err.println("读取CSV出错：" + e.getMessage());
            e.printStackTrace();
        }

        ParentTest.writeGeoJson(aisPointsByMmsi, outPath);
        AisPointBatchInsert.addAisPoint(aisPointsByMmsi, uuid);

        // 原始点保存 postgis
//        ShipInfoBatchInsert.insertShipInfo(aisPointsByMmsi, uuid);
        return aisPointsByMmsi;
    }




    // CSVRecord → AisPoint
    private static AisPoint toAisPoint(CSVRecord r) {
        AisPoint p = new AisPoint();
        p.setMmsi(parseLong(r.get("mmsi")));
        p.setImo(r.get("imo"));
        p.setNationality(r.get("nationality"));
        p.setName(r.get("name"));
        p.setCallsign(r.get("callsign"));
        p.setLength(parseDouble(r.get("length")));
        p.setWidth(parseDouble(r.get("width")));
        p.setLeft(parseDouble(r.get("left")));
        p.setTail(parseDouble(r.get("tail")));
        p.setDraught(parseDouble(r.get("draught")));
        p.setDest(r.get("dest"));
        p.setEta(r.get("eta"));
        p.setLon(parseDouble(r.get("lon")));
        p.setLat(parseDouble(r.get("lat")));
        p.setHdg(parseDouble(r.get("hdg")));
        p.setCog(parseDouble(r.get("cog")));
        p.setSpeed(parseDouble(r.get("speed")));
        p.setRot(parseDouble(r.get("rot")));
        p.setTime(new Timestamp(Long.parseLong(r.get("time")) * 1000));
        p.setShiptype(parseInt(r.get("shiptype")));
        p.setEtaStd(parseTimestamp(r.get("eta_std")));
        p.setNavistat(parseInt(r.get("navistat")));
        return p;
    }

    // 去重工具
    private static <T> java.util.function.Predicate<T> distinctByKey(java.util.function.Function<? super T, ?> keyExtractor) {
        Set<Object> seen = Collections.synchronizedSet(new HashSet<>());
        return t -> seen.add(keyExtractor.apply(t));
    }

    private static Long parseLong(String s) {
        try { return Long.parseLong(s); } catch (Exception e) { return null; }
    }
    private static Integer parseInt(String s) {
        try { return Integer.parseInt(s); } catch (Exception e) { return null; }
    }
    private static Double parseDouble(String s) {
        try { return Double.parseDouble(s); } catch (Exception e) { return null; }
    }
    private static Timestamp parseTimestamp(String s) {
        try { return Timestamp.valueOf(s); } catch (Exception e) { return null; }
    }
}
